<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频音频分离工具</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/ffmpeg/0.11.6/ffmpeg.min.js"></script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --warning-color: #feca57;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --glass-bg: rgba(255, 255, 255, 0.25);
        --glass-border: rgba(255, 255, 255, 0.18);
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        transition: all 0.3s ease;
        animation: pageLoad 0.8s ease;
      }

      @keyframes pageLoad {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .container {
        width: 100%;
        max-width: 1200px;
        background: var(--primary-bg);
        border-radius: 30px;
        padding: 40px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        margin-top: 20px;
        transition: all 0.3s ease;
        animation: containerFloat 1s ease 0.2s both;
      }

      @keyframes containerFloat {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerSlide 0.8s ease 0.4s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateY(-30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 3.2rem;
        margin-bottom: 15px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        animation: titleGlow 3s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.2);
        }
      }

      .subtitle {
        font-size: 1.3rem;
        color: var(--text-secondary);
        margin-bottom: 30px;
        font-weight: 500;
      }

      .panels {
        display: flex;
        gap: 30px;
        margin-bottom: 40px;
        animation: panelsSlide 0.8s ease 0.6s both;
      }

      @keyframes panelsSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .panel {
        flex: 1;
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
      }

      .panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .panel:hover::before {
        left: 100%;
      }

      .panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .panel-title {
        font-size: 1.6rem;
        margin-bottom: 25px;
        color: var(--accent-color);
        display: flex;
        align-items: center;
        font-weight: 600;
      }

      .panel-title::before {
        content: attr(data-icon);
        margin-right: 12px;
        font-size: 1.8rem;
        animation: iconBounce 2s ease-in-out infinite;
      }

      @keyframes iconBounce {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
      }

      .file-upload {
        border: 3px dashed var(--accent-color);
        border-radius: 25px;
        padding: 50px 40px;
        text-align: center;
        transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        margin-bottom: 25px;
        cursor: pointer;
        background: var(--primary-bg);
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      .file-upload:hover {
        border-color: var(--success-color);
        transform: translateY(-5px) scale(1.02);
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light),
          0 15px 40px rgba(102, 126, 234, 0.25), 0 5px 15px rgba(0, 0, 0, 0.1);
      }

      .file-upload.dragover {
        border-color: var(--success-color);
        background: rgba(78, 205, 196, 0.05);
        transform: scale(1.05);
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light),
          0 20px 50px rgba(78, 205, 196, 0.3);
        animation: dragPulse 1s ease-in-out infinite;
      }

      @keyframes dragPulse {
        0%,
        100% {
          border-color: var(--success-color);
        }
        50% {
          border-color: var(--accent-color);
        }
      }

      .file-upload-content {
        position: relative;
        z-index: 1;
      }

      .file-upload-icon {
        font-size: 3.5rem;
        margin-bottom: 20px;
        display: block;
        animation: iconFloat 3s ease-in-out infinite;
        filter: drop-shadow(0 4px 8px rgba(102, 126, 234, 0.2));
      }

      @keyframes iconFloat {
        0%,
        100% {
          transform: translateY(0);
        }
        50% {
          transform: translateY(-10px);
        }
      }

      .file-upload-text {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 10px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
      }

      .file-upload-subtext {
        font-size: 1.1rem;
        color: var(--text-secondary);
        margin-bottom: 20px;
        font-weight: 500;
      }

      .file-upload-formats {
        font-size: 0.9rem;
        color: var(--accent-color);
        font-weight: 500;
        padding: 8px 16px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 20px;
        display: inline-block;
        margin-bottom: 20px;
      }

      .file-upload input[type='file'] {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        opacity: 0;
        cursor: pointer;
        z-index: 2;
      }

      .video-preview {
        width: 100%;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-top: 20px;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .video-preview:hover {
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light);
      }

      video {
        width: 100%;
        max-height: 300px;
        display: block;
        border-radius: 15px;
      }

      .options-form {
        display: flex;
        gap: 20px;
        margin-bottom: 25px;
        flex-wrap: wrap;
        align-items: flex-end;
      }

      .form-group {
        flex: 1;
        min-width: 150px;
      }

      label {
        display: block;
        margin-bottom: 10px;
        color: var(--text-secondary);
        font-weight: 500;
        font-size: 0.95rem;
      }

      input,
      select {
        width: 100%;
        padding: 14px 18px;
        background: var(--primary-bg);
        border: none;
        border-radius: 15px;
        color: var(--text-primary);
        font-size: 1rem;
        font-weight: 500;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
      }

      input:focus,
      select:focus {
        outline: none;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light),
          0 0 0 3px rgba(102, 126, 234, 0.2);
      }

      button {
        background: var(--primary-bg);
        color: var(--text-primary);
        border: none;
        padding: 14px 28px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        font-size: 1rem;
        flex-shrink: 0;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      button:hover::before {
        left: 100%;
      }

      button:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      button:active {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        padding: 16px 32px;
        font-size: 1.1rem;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-primary:hover {
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2),
          0 0 30px rgba(102, 126, 234, 0.3);
      }

      .btn-success {
        background: linear-gradient(
          135deg,
          var(--success-color) 0%,
          #44a08d 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .progress-container {
        margin: 30px 0;
        animation: progressSlide 0.8s ease 0.8s both;
      }

      @keyframes progressSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .progress-bar {
        height: 16px;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-bottom: 15px;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        position: relative;
      }

      .progress-fill {
        height: 100%;
        background: var(--accent-gradient);
        width: 0%;
        transition: width 0.3s ease;
        border-radius: 20px;
        box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
        position: relative;
        overflow: hidden;
      }

      .progress-fill::after {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.3),
          transparent
        );
        animation: progressShine 2s infinite;
      }

      @keyframes progressShine {
        0% {
          left: -100%;
        }
        100% {
          left: 100%;
        }
      }

      .progress-text {
        text-align: center;
        font-size: 1rem;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .actions {
        display: flex;
        justify-content: center;
        gap: 25px;
        margin-top: 30px;
        animation: actionsSlide 0.8s ease 1s both;
      }

      @keyframes actionsSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .result-panel {
        text-align: center;
        animation: resultPanelSlide 0.8s ease 1.2s both;
      }

      @keyframes resultPanelSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .status-message {
        min-height: 35px;
        margin: 20px 0;
        color: var(--accent-color);
        font-weight: 600;
        font-size: 1.1rem;
        transition: all 0.3s ease;
      }

      .status-message.processing {
        animation: statusPulse 1.5s ease-in-out infinite;
      }

      @keyframes statusPulse {
        0%,
        100% {
          opacity: 1;
        }
        50% {
          opacity: 0.6;
        }
      }

      .error-message {
        color: var(--danger-color);
        margin: 20px 0;
        min-height: 35px;
        font-weight: 600;
        font-size: 1.1rem;
        animation: errorShake 0.5s ease;
      }

      @keyframes errorShake {
        0%,
        100% {
          transform: translateX(0);
        }
        25% {
          transform: translateX(-5px);
        }
        75% {
          transform: translateX(5px);
        }
      }

      .download-section {
        display: flex;
        flex-direction: column;
        gap: 20px;
        margin-top: 30px;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: var(--border-radius);
        box-shadow: var(--shadow-large);
        border: 2px solid var(--accent-color);
      }

      .download-segments {
        display: flex;
        flex-direction: column;
        gap: 25px;
      }

      .download-segment {
        background: var(--primary-bg);
        border-radius: var(--border-radius);
        padding: 20px;
        box-shadow: var(--shadow-medium);
        border: 1px solid rgba(102, 126, 234, 0.2);
        transition: all 0.3s ease;
      }

      .download-segment:hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-large);
        border-color: var(--accent-color);
      }

      .segment-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
        padding-bottom: 10px;
        border-bottom: 1px solid rgba(102, 126, 234, 0.2);
      }

      .segment-header h4 {
        margin: 0;
        color: var(--text-primary);
        font-size: 1.1rem;
        font-weight: 600;
      }

      .segment-time {
        color: var(--text-secondary);
        font-size: 0.9rem;
        font-weight: 500;
        background: rgba(102, 126, 234, 0.1);
        padding: 4px 12px;
        border-radius: 15px;
        border: 1px solid rgba(102, 126, 234, 0.2);
      }

      .download-items {
        display: flex;
        gap: 15px;
        flex-wrap: wrap;
      }

      .download-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 15px;
        background: var(--primary-bg);
        border-radius: var(--border-radius);
        box-shadow: var(--shadow-small);
        transition: all 0.3s ease;
        border: 1px solid rgba(102, 126, 234, 0.1);
        flex: 1;
        min-width: 280px;
      }

      .download-item:hover {
        transform: translateY(-1px);
        box-shadow: var(--shadow-medium);
        border-color: var(--accent-color);
      }

      .download-title {
        font-size: 1rem;
        font-weight: 600;
        color: var(--text-primary);
        display: flex;
        align-items: center;
        gap: 8px;
      }

      .download-size {
        font-size: 0.9rem;
        color: var(--text-secondary);
        font-weight: 500;
        padding: 6px 12px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        border: 1px solid rgba(102, 126, 234, 0.2);
        margin: 0 10px;
      }

      .instructions {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 40px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: instructionsSlide 0.8s ease 1.4s both;
      }

      @keyframes instructionsSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions h3 {
        color: var(--accent-color);
        margin-bottom: 20px;
        font-size: 1.4rem;
        font-weight: 600;
      }

      .instructions ol {
        padding-left: 25px;
        margin-bottom: 20px;
      }

      .instructions li {
        margin-bottom: 12px;
        line-height: 1.7;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .instructions p {
        color: var(--text-secondary);
        font-style: italic;
        font-weight: 500;
        padding: 15px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        border-left: 4px solid var(--accent-color);
      }

      footer {
        margin-top: 40px;
        text-align: center;
        color: var(--text-secondary);
        font-size: 0.95rem;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        animation: footerFade 0.8s ease 1.6s both;
      }

      @keyframes footerFade {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      /* 预览弹窗样式 */
      .preview-modal {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.8);
        display: none;
        justify-content: center;
        align-items: center;
        z-index: 1000;
        animation: modalFadeIn 0.3s ease;
      }

      @keyframes modalFadeIn {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      .preview-content {
        background: var(--primary-bg);
        border-radius: 20px;
        padding: 30px;
        max-width: 90vw;
        min-width: 50vw;
        max-height: 90vh;
        position: relative;
        animation: modalSlideIn 0.3s ease;
      }

      @keyframes modalSlideIn {
        from {
          transform: scale(0.8) translateY(-20px);
          opacity: 0;
        }
        to {
          transform: scale(1) translateY(0);
          opacity: 1;
        }
      }

      .preview-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20px;
        padding-bottom: 15px;
        border-bottom: 2px solid rgba(102, 126, 234, 0.2);
      }

      .preview-title {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--accent-color);
        margin: 0;
      }

      .close-btn {
        background: var(--danger-color);
        color: white;
        border: none;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        cursor: pointer;
        font-size: 1.2rem;
        font-weight: bold;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s ease;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
        padding: 0;
      }

      .close-btn:hover {
        transform: scale(1.1);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      .preview-media {
        width: 100%;
        max-width: 800px;
        max-height: 600px;
        border-radius: 15px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
      }

      .preview-btn {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        padding: 8px 16px;
        border-radius: 12px;
        cursor: pointer;
        font-size: 0.9rem;
        font-weight: 600;
        margin-left: 10px;
        transition: all 0.3s ease;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .preview-btn:hover {
        transform: translateY(-2px);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      /* 时间段管理样式 */
      .time-segments-section {
        margin-bottom: 25px;
      }

      .section-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20px;
        padding-bottom: 15px;
        border-bottom: 2px solid rgba(102, 126, 234, 0.1);
      }

      .section-header h4 {
        color: var(--accent-color);
        font-size: 1.3rem;
        font-weight: 600;
        margin: 0;
      }

      .current-time-display {
        background: var(--primary-bg);
        padding: 8px 16px;
        border-radius: 12px;
        font-size: 0.9rem;
        color: var(--text-secondary);
        font-weight: 500;
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
      }

      .time-input-form {
        background: var(--primary-bg);
        border-radius: 20px;
        padding: 25px;
        margin-bottom: 25px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
      }

      .input-with-button {
        display: flex;
        gap: 10px;
        align-items: center;
      }

      .input-with-button input {
        flex: 1;
      }

      .get-time-btn {
        background: var(--accent-gradient);
        color: white;
        border: none;
        padding: 12px 16px;
        border-radius: 12px;
        cursor: pointer;
        font-size: 1.2rem;
        transition: all 0.3s ease;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        flex-shrink: 0;
      }

      .get-time-btn:hover {
        transform: translateY(-2px);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .get-time-btn:active {
        transform: translateY(0);
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
      }

      .add-segment-btn {
        background: var(--success-color);
        color: white;
        border: none;
        padding: 14px 24px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        font-size: 1rem;
        margin-top: 15px;
        width: 100%;
        transition: all 0.3s ease;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .add-segment-btn:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      .segments-list {
        background: var(--primary-bg);
        border-radius: 20px;
        padding: 20px;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      .segments-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
        padding-bottom: 10px;
        border-bottom: 1px solid rgba(102, 126, 234, 0.1);
      }

      .segments-header span:first-child {
        color: var(--accent-color);
        font-weight: 600;
        font-size: 1.1rem;
      }

      .segments-count {
        background: rgba(102, 126, 234, 0.1);
        color: var(--accent-color);
        padding: 4px 12px;
        border-radius: 12px;
        font-size: 0.85rem;
        font-weight: 500;
      }

      .segments-container {
        max-height: 300px;
        overflow-y: auto;
      }

      .empty-segments {
        text-align: center;
        padding: 40px 20px;
        color: var(--text-secondary);
        font-style: italic;
      }

      .segment-item {
        background: var(--primary-bg);
        padding: 15px;
        margin-bottom: 10px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
        animation: segmentSlideIn 0.3s ease;
      }

      @keyframes segmentSlideIn {
        from {
          opacity: 0;
          transform: translateY(-10px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .segment-item:hover {
        transform: translateY(-2px);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .segment-info {
        flex: 1;
      }

      .segment-time {
        font-weight: 600;
        color: var(--text-primary);
        font-size: 1rem;
        margin-bottom: 5px;
      }

      .segment-duration {
        font-size: 0.85rem;
        color: var(--text-secondary);
      }

      .segment-actions {
        display: flex;
        gap: 8px;
      }

      .segment-delete-btn {
        background: var(--danger-color);
        color: white;
        border: none;
        padding: 8px 12px;
        border-radius: 10px;
        cursor: pointer;
        font-size: 0.9rem;
        transition: all 0.3s ease;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .segment-delete-btn:hover {
        transform: translateY(-2px);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      /* 响应式设计 */
      @media (max-width: 1024px) {
        .container {
          padding: 30px;
          margin: 10px;
        }

        .panels {
          flex-direction: column;
        }

        h1 {
          font-size: 2.5rem;
        }

        .subtitle {
          font-size: 1.1rem;
        }
      }

      @media (max-width: 768px) {
        .container {
          padding: 20px;
        }

        .options-form {
          flex-direction: column;
        }

        .actions {
          flex-direction: column;
          align-items: center;
        }

        .download-section {
          flex-direction: column;
          align-items: center;
        }

        h1 {
          font-size: 2rem;
        }

        .file-upload {
          padding: 30px 20px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <header>
        <h1>🎵 视频音频分离工具</h1>
        <p class="subtitle">基于 FFmpeg 的高质量音视频分离处理</p>
      </header>

      <div class="panels">
        <!-- 上传面板 -->
        <div class="panel">
          <div class="panel-title" data-icon="📁">文件上传</div>
          <div class="file-upload" id="uploadArea">
            <div class="file-upload-content">
              <span class="file-upload-icon">🎬</span>
              <div class="file-upload-text">拖拽视频文件到此处或点击上传</div>
              <div class="file-upload-subtext">支持所有主流视频格式</div>
              <div class="file-upload-formats">
                MP4, AVI, MOV, MKV, WMV, FLV, WebM, M4V, 3GP, TS, MTS
              </div>
              <input type="file" id="videoInput" accept="video/*" />
            </div>
          </div>

          <div class="video-preview" id="originalPreview">
            <p
              style="
                text-align: center;
                padding: 60px 20px;
                color: var(--text-secondary);
                font-size: 1.1rem;
              "
            >
              📺 视频预览区
            </p>
          </div>
        </div>

        <!-- 设置面板 -->
        <div class="panel">
          <div class="panel-title" data-icon="⚙️">分离设置</div>

          <!-- 时间段管理 -->
          <div class="time-segments-section">
            <div class="section-header">
              <h4>🎯 时间段设置</h4>
              <div class="current-time-display" id="currentTimeDisplay">
                当前时间: 00:00
              </div>
            </div>

            <div class="time-input-form">
              <div class="form-group">
                <label for="newStartTime">开始时间 (秒)</label>
                <div class="input-with-button">
                  <input
                    type="number"
                    id="newStartTime"
                    value="0"
                    min="0"
                    step="0.1"
                    placeholder="开始时间"
                  />
                  <button
                    type="button"
                    class="get-time-btn"
                    id="getStartTimeBtn"
                    title="获取当前播放时间"
                  >
                    📍
                  </button>
                </div>
              </div>
              <div class="form-group">
                <label for="newEndTime">结束时间 (秒)</label>
                <div class="input-with-button">
                  <input
                    type="number"
                    id="newEndTime"
                    value=""
                    min="0"
                    step="0.1"
                    placeholder="结束时间"
                  />
                  <button
                    type="button"
                    class="get-time-btn"
                    id="getEndTimeBtn"
                    title="获取当前播放时间"
                  >
                    📍
                  </button>
                </div>
              </div>
              <button type="button" class="add-segment-btn" id="addSegmentBtn">
                ➕ 添加时间段
              </button>
            </div>

            <div class="segments-list" id="segmentsList">
              <div class="segments-header">
                <span>📋 时间段列表</span>
                <span class="segments-count" id="segmentsCount">0 个片段</span>
              </div>
              <div class="segments-container" id="segmentsContainer">
                <div class="empty-segments">
                  <p>🎬 暂无时间段，请添加要分离的时间段</p>
                </div>
              </div>
            </div>
          </div>

          <div class="options-form">
            <div class="form-group">
              <label for="videoFormat">视频格式</label>
              <select id="videoFormat">
                <option value="mp4">MP4 (推荐)</option>
                <option value="avi">AVI</option>
                <option value="mov">MOV</option>
                <option value="mkv">MKV</option>
                <option value="webm">WebM</option>
                <option value="flv">FLV</option>
                <option value="wmv">WMV</option>
                <option value="m4v">M4V</option>
                <option value="3gp">3GP</option>
                <option value="ts">TS</option>
              </select>
            </div>
            <div class="form-group">
              <label for="audioFormat">音频格式</label>
              <select id="audioFormat">
                <option value="mp3">MP3 (推荐)</option>
                <option value="wav">WAV</option>
                <option value="aac">AAC</option>
                <option value="flac">FLAC</option>
                <option value="ogg">OGG</option>
                <option value="m4a">M4A</option>
                <option value="wma">WMA</option>
              </select>
            </div>
          </div>

          <div class="options-form">
            <div class="form-group">
              <label for="videoQuality">视频质量</label>
              <select id="videoQuality">
                <option value="original">原始质量</option>
                <option value="high">高质量 (CRF 18)</option>
                <option value="medium">中等质量 (CRF 23)</option>
                <option value="low">低质量 (CRF 28)</option>
              </select>
            </div>
            <div class="form-group">
              <label for="audioBitrate">音频比特率</label>
              <select id="audioBitrate">
                <option value="320">320 kbps (高质量)</option>
                <option value="256">256 kbps</option>
                <option value="192">192 kbps (推荐)</option>
                <option value="128">128 kbps</option>
                <option value="96">96 kbps</option>
              </select>
            </div>
          </div>

          <div class="actions">
            <button class="btn-primary" id="processBtn" disabled>
              🚀 开始分离
            </button>
            <button id="resetBtn">🔄 重置</button>
          </div>
        </div>
      </div>

      <!-- 进度显示 -->
      <div class="progress-container">
        <div class="progress-bar">
          <div class="progress-fill" id="progressFill"></div>
        </div>
        <div class="progress-text" id="progressText">🚀 准备就绪</div>
      </div>

      <!-- 状态信息 -->
      <div class="status-message" id="statusMessage"></div>
      <div class="error-message" id="errorMessage"></div>

      <!-- 下载区域 -->
      <div class="download-section" id="downloadSection" style="display: none">
        <div class="download-segments" id="downloadSegments">
          <!-- 动态生成的片段下载项 -->
        </div>
      </div>

      <!-- 使用说明 -->
      <div class="instructions">
        <h3>📖 使用说明</h3>
        <ol>
          <li>选择或拖拽视频文件到上传区域</li>
          <li>设置分离参数（时间范围、格式、质量等）</li>
          <li>点击"开始分离"按钮进行处理</li>
          <li>处理完成后可分别下载视频和音频文件</li>
        </ol>
        <p>
          💡
          提示：支持指定时间范围分离，留空结束时间将处理完整视频。支持多种输出格式和质量选项。
        </p>
      </div>

      <footer>
        <p>🔧 基于 FFmpeg.wasm 技术 | 🌐 完全在浏览器中运行，保护您的隐私</p>
      </footer>
</div>
    </div>

    <!-- 预览弹窗 -->
    <div id="previewModal" class="preview-modal">
      <div class="preview-content">
        <div class="preview-header">
          <h3 class="preview-title" id="previewTitle">文件预览</h3>
          <button class="close-btn" id="closePreview">×</button>
        </div>
        <div id="previewContainer"></div>
      </div>
    </div>

    <script>
      let ffmpeg = null
      let inputFile = null
      let videoUrl = null
      let videoBlob = null
      let audioBlob = null

      // 时间段管理
      let timeSegments = []
      let currentVideo = null

      // DOM 元素
      const uploadArea = document.getElementById('uploadArea')
      const videoInput = document.getElementById('videoInput')
      const originalPreview = document.getElementById('originalPreview')
      const startTimeInput = document.getElementById('newStartTime')
      const endTimeInput = document.getElementById('newEndTime')
      const getStartTimeBtn = document.getElementById('getStartTimeBtn')
      const getEndTimeBtn = document.getElementById('getEndTimeBtn')
      const addSegmentBtn = document.getElementById('addSegmentBtn')
      const segmentsList = document.getElementById('segmentsList')
      const segmentsCount = document.getElementById('segmentsCount')
      const currentTimeDisplay = document.getElementById('currentTimeDisplay')
      const videoFormatSelect = document.getElementById('videoFormat')
      const audioFormatSelect = document.getElementById('audioFormat')
      const videoQualitySelect = document.getElementById('videoQuality')
      const audioBitrateSelect = document.getElementById('audioBitrate')
      const processBtn = document.getElementById('processBtn')
      const resetBtn = document.getElementById('resetBtn')
      const progressFill = document.getElementById('progressFill')
      const progressText = document.getElementById('progressText')
      const statusMessage = document.getElementById('statusMessage')
      const errorMessage = document.getElementById('errorMessage')
      const downloadSection = document.getElementById('downloadSection')
      const downloadSegments = document.getElementById('downloadSegments')

      // 初始化事件
      function initEvents() {
        // 文件上传事件
        videoInput.addEventListener('change', handleFileUpload)
        uploadArea.addEventListener('click', (e) => {
          // 只有在没有文件时才触发文件选择
          if (!inputFile && e.target === uploadArea) {
            videoInput.click()
          }
        })

        // 拖拽事件
        uploadArea.addEventListener('dragover', (e) => {
          e.preventDefault()
          uploadArea.classList.add('dragover')
        })

        uploadArea.addEventListener('dragleave', (e) => {
          e.preventDefault()
          uploadArea.classList.remove('dragover')
        })

        uploadArea.addEventListener('drop', (e) => {
          e.preventDefault()
          uploadArea.classList.remove('dragover')

          if (e.dataTransfer.files.length) {
            videoInput.files = e.dataTransfer.files
            handleFileUpload({ target: { files: e.dataTransfer.files } })
          }
        })

        // 按钮事件
        processBtn.addEventListener('click', processVideo)
        resetBtn.addEventListener('click', resetAll)

        // 时间段管理事件
        getStartTimeBtn.addEventListener('click', () => getCurrentTime('start'))
        getEndTimeBtn.addEventListener('click', () => getCurrentTime('end'))
        addSegmentBtn.addEventListener('click', addTimeSegment)
      }

      // 处理文件上传
      function handleFileUpload(event) {
        const file = event.target.files[0]
        if (!file) return

        // 检查文件类型
        if (!file.type.match('video.*')) {
          showError('❌ 请上传视频文件', errorMessage)
          return
        }

        inputFile = file
        videoUrl = URL.createObjectURL(file)

        // 显示视频预览
        originalPreview.innerHTML = `
          <video controls style="border-radius: 15px;">
            <source src="${videoUrl}" type="${file.type}">
            您的浏览器不支持视频预览
          </video>
          <p style="text-align: center; padding: 15px 0; color: var(--text-secondary); font-weight: 500;">
            📁 ${file.name} (${formatFileSize(file.size)})
          </p>
        `

        // 获取视频元素引用
        currentVideo = originalPreview.querySelector('video')

        // 获取视频时长并设置默认结束时间
        currentVideo.addEventListener('loadedmetadata', () => {
          if (!endTimeInput.value) {
            endTimeInput.value = Math.floor(currentVideo.duration)
          }
        })

        // 监听时间更新
        currentVideo.addEventListener('timeupdate', updateCurrentTime)

        // 启用处理按钮
        processBtn.disabled = false
        downloadSection.style.display = 'none'
        statusMessage.textContent = '✨ 请设置分离参数并开始处理'
      }

      // 时间段管理功能
      function updateCurrentTime() {
        if (currentVideo) {
          const currentTime = currentVideo.currentTime
          const minutes = Math.floor(currentTime / 60)
          const seconds = Math.floor(currentTime % 60)
          currentTimeDisplay.textContent = `${minutes
            .toString()
            .padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
        }
      }

      function getCurrentTime(type) {
        if (!currentVideo) {
          showError('❌ 请先上传视频文件', errorMessage)
          return
        }

        const currentTime = Math.floor(currentVideo.currentTime)

        if (type === 'start') {
          startTimeInput.value = currentTime
          statusMessage.textContent = `⏰ 已设置开始时间: ${formatTime(
            currentTime
          )}`
        } else if (type === 'end') {
          endTimeInput.value = currentTime
          statusMessage.textContent = `⏰ 已设置结束时间: ${formatTime(
            currentTime
          )}`
        }
      }

      function addTimeSegment() {
        const startTime = parseFloat(startTimeInput.value)
        const endTime = parseFloat(endTimeInput.value)

        if (isNaN(startTime) || isNaN(endTime)) {
          showError('❌ 请输入有效的开始和结束时间', errorMessage)
          return
        }

        if (startTime >= endTime) {
          showError('❌ 开始时间必须小于结束时间', errorMessage)
          return
        }

        if (currentVideo && endTime > currentVideo.duration) {
          showError('❌ 结束时间不能超过视频总时长', errorMessage)
          return
        }

        // 检查时间段重叠
        const hasOverlap = timeSegments.some(
          (segment) => startTime < segment.end && endTime > segment.start
        )

        if (hasOverlap) {
          if (!confirm('⚠️ 检测到时间段重叠，是否继续添加？')) {
            return
          }
        }

        const segment = {
          id: Date.now(),
          start: startTime,
          end: endTime,
          duration: endTime - startTime,
        }

        timeSegments.push(segment)
        updateSegmentsList()

        // 清空输入框
        startTimeInput.value = ''
        endTimeInput.value = ''

        statusMessage.textContent = `✅ 已添加时间段: ${formatTime(
          startTime
        )} - ${formatTime(endTime)}`
      }

      function removeTimeSegment(id) {
        timeSegments = timeSegments.filter((segment) => segment.id !== id)
        updateSegmentsList()
        statusMessage.textContent = '🗑️ 已删除时间段'
      }

      function updateSegmentsList() {
        segmentsCount.textContent = `${timeSegments.length} 个片段`

        const segmentsContainer = document.getElementById('segmentsContainer')

        if (timeSegments.length === 0) {
          segmentsContainer.innerHTML =
            '<div class="empty-segments"><p>🎬 暂无时间段，请添加要分离的时间段</p></div>'
          processBtn.disabled = true
          return
        }

        // 按开始时间排序
        timeSegments.sort((a, b) => a.start - b.start)

        segmentsContainer.innerHTML = timeSegments
          .map(
            (segment, index) => `
          <div class="segment-item" data-id="${segment.id}">
            <div class="segment-info">
              <div class="segment-title">片段 ${index + 1}</div>
              <div class="segment-time">${formatTime(
                segment.start
              )} - ${formatTime(segment.end)}</div>
              <div class="segment-duration">(时长: ${formatTime(
                segment.duration
              )})</div>
            </div>
            <div class="segment-actions">
              <button class="segment-delete-btn" onclick="removeTimeSegment(${
                segment.id
              })" title="删除片段">
                🗑️ 删除
              </button>
            </div>
          </div>
        `
          )
          .join('')

        // 启用处理按钮
        if (inputFile) {
          processBtn.disabled = false
        }
      }

      function formatTime(seconds) {
        const minutes = Math.floor(seconds / 60)
        const secs = Math.floor(seconds % 60)
        return `${minutes}:${secs.toString().padStart(2, '0')}`
      }

      // 处理视频分离
      async function processVideo() {
        if (!inputFile) {
          showError('❌ 请先上传视频文件', errorMessage)
          return
        }

        if (timeSegments.length === 0) {
          showError('❌ 请至少添加一个时间段', errorMessage)
          return
        }

        try {
          statusMessage.textContent = '🚀 正在加载FFmpeg引擎...'
          statusMessage.classList.add('processing')
          errorMessage.textContent = ''
          processBtn.disabled = true
          // Download buttons are now dynamically generated
          downloadSection.style.display = 'none'

          // 初始化FFmpeg
          if (!ffmpeg) {
            const { createFFmpeg, fetchFile } = FFmpeg
            ffmpeg = createFFmpeg({
              log: true,
            })

            // 监听进度
            ffmpeg.setProgress(({ ratio }) => {
              const percent = Math.floor(ratio * 100)
              progressFill.style.width = `${percent}%`
              progressText.textContent = `🎯 处理中: ${percent}%`
            })

            await ffmpeg.load()
          }

          const { fetchFile } = FFmpeg
          const videoFormat = videoFormatSelect.value
          const audioFormat = audioFormatSelect.value
          const videoQuality = videoQualitySelect.value
          const audioBitrate = audioBitrateSelect.value

          // 写入视频文件到虚拟文件系统
          const inputName = 'input.' + inputFile.name.split('.').pop()
          ffmpeg.FS('writeFile', inputName, await fetchFile(inputFile))

          // 处理多个时间段
          const segmentBlobs = []

          statusMessage.textContent = `🎬 正在处理 ${timeSegments.length} 个时间段...`

          for (let i = 0; i < timeSegments.length; i++) {
            const segment = timeSegments[i]
            const segmentVideoName = `video_segment_${i}.${videoFormat}`
            const segmentAudioName = `audio_segment_${i}.${audioFormat}`

            statusMessage.textContent = `🎬 正在处理第 ${i + 1}/${
              timeSegments.length
            } 个片段...`

            // 处理视频片段
            const videoArgs = ['-i', inputName]
            
            // 只有当开始时间大于0时才添加-ss参数，避免从0开始时的黑屏问题
            if (segment.start > 0) {
              videoArgs.push('-ss', segment.start.toString())
            }
            
            videoArgs.push('-t', segment.duration.toString(), '-an')
            // 重置时间戳，确保输出视频从0开始播放
            videoArgs.push('-avoid_negative_ts', 'make_zero')

            // 设置视频质量
            if (videoQuality === 'original') {
              videoArgs.push('-c:v', 'copy')
            } else {
              videoArgs.push('-c:v', 'libx264')
              const crfMap = { high: '18', medium: '23', low: '28' }
              videoArgs.push('-crf', crfMap[videoQuality])
            }

            videoArgs.push(segmentVideoName)
            await ffmpeg.run(...videoArgs)

            // 处理音频片段
            const audioArgs = ['-i', inputName]
            
            // 只有当开始时间大于0时才添加-ss参数，避免从0开始时的黑屏问题
            if (segment.start > 0) {
              audioArgs.push('-ss', segment.start.toString())
            }
            
            audioArgs.push('-t', segment.duration.toString(), '-vn')
            // 重置时间戳，确保输出音频从0开始播放
            audioArgs.push('-avoid_negative_ts', 'make_zero')
            audioArgs.push('-c:a', getAudioCodec(audioFormat))
            audioArgs.push('-b:a', `${audioBitrate}k`)
            audioArgs.push(segmentAudioName)

            await ffmpeg.run(...audioArgs)

            // 读取片段文件
            const videoData = ffmpeg.FS('readFile', segmentVideoName)
            const audioData = ffmpeg.FS('readFile', segmentAudioName)

            const videoBlob = new Blob([videoData.buffer], {
              type: `video/${videoFormat}`,
            })
            const audioBlob = new Blob([audioData.buffer], {
              type: `audio/${audioFormat}`,
            })

            segmentBlobs.push({
              index: i,
              segment: segment,
              videoBlob: videoBlob,
              audioBlob: audioBlob,
            })

            // 清理临时文件
            ffmpeg.FS('unlink', segmentVideoName)
            ffmpeg.FS('unlink', segmentAudioName)
          }

          // 生成下载区域
          generateDownloadArea(segmentBlobs, videoFormat, audioFormat)

          // 显示下载区域
          downloadSection.style.display = 'flex'

          statusMessage.textContent = `🎉 多时间段音视频分离完成！共处理 ${timeSegments.length} 个片段`
          statusMessage.classList.remove('processing')
          progressText.textContent = '✅ 处理完成'
          progressFill.style.width = '100%'
        } catch (error) {
          console.error('处理失败:', error)
          showError(`❌ 处理失败: ${error.message}`, errorMessage)
          statusMessage.classList.remove('processing')
          processBtn.disabled = false
        }
      }

      // 获取音频编码器
      function getAudioCodec(format) {
        const codecMap = {
          mp3: 'libmp3lame',
          wav: 'pcm_s16le',
          aac: 'aac',
          flac: 'flac',
          ogg: 'libvorbis',
          m4a: 'aac',
          wma: 'wmav2',
        }
        return codecMap[format] || 'aac'
      }

      // 生成下载区域
      function generateDownloadArea(segmentBlobs, videoFormat, audioFormat) {
        downloadSegments.innerHTML = ''

        segmentBlobs.forEach((segmentData, index) => {
          const segmentDiv = document.createElement('div')
          segmentDiv.className = 'download-segment'
          
          // 检查是否支持预览
          const videoSupportsPreview = isPreviewSupported('video', videoFormat)
          const audioSupportsPreview = isPreviewSupported('audio', audioFormat)
          
          segmentDiv.innerHTML = `
            <div class="segment-header">
              <h4>片段 ${index + 1}</h4>
              <span class="segment-time">${formatTime(
                segmentData.segment.start
              )} - ${formatTime(segmentData.segment.end)}</span>
            </div>
            <div class="download-items">
              <div class="download-item">
                <div class="download-title">🎬 视频文件</div>
                <div class="download-size">${formatFileSize(
                  segmentData.videoBlob.size
                )}</div>
                <button class="btn-success download-btn" data-type="video" data-index="${index}">
                  📥 下载视频
                </button>
                ${videoSupportsPreview ? `<button class="preview-btn" data-type="video" data-index="${index}">
                  👁️ 预览
                </button>` : ''}
              </div>
              <div class="download-item">
                <div class="download-title">🎵 音频文件</div>
                <div class="download-size">${formatFileSize(
                  segmentData.audioBlob.size
                )}</div>
                <button class="btn-success download-btn" data-type="audio" data-index="${index}">
                  📥 下载音频
                </button>
                ${audioSupportsPreview ? `<button class="preview-btn" data-type="audio" data-index="${index}">
                  👁️ 预览
                </button>` : ''}
              </div>
            </div>
          `
          downloadSegments.appendChild(segmentDiv)
        })

        // 添加下载按钮事件监听
        document.querySelectorAll('.download-btn').forEach((btn) => {
          btn.addEventListener('click', (e) => {
            const type = e.target.getAttribute('data-type')
            const index = parseInt(e.target.getAttribute('data-index'))
            downloadSegmentFile(
              segmentBlobs[index],
              type,
              videoFormat,
              audioFormat,
              index + 1
            )
          })
        })
        
        // 添加预览按钮事件监听
        document.querySelectorAll('.preview-btn').forEach((btn) => {
          btn.addEventListener('click', (e) => {
            const type = e.target.getAttribute('data-type')
            const index = parseInt(e.target.getAttribute('data-index'))
            previewFile(
              segmentBlobs[index],
              type,
              videoFormat,
              audioFormat,
              index + 1
            )
          })
        })
      }

      // 下载片段文件
      function downloadSegmentFile(
        segmentData,
        type,
        videoFormat,
        audioFormat,
        segmentNumber
      ) {
        const blob =
          type === 'video' ? segmentData.videoBlob : segmentData.audioBlob
        const format = type === 'video' ? videoFormat : audioFormat
        const timestamp = new Date()
          .toISOString()
          .slice(0, 19)
          .replace(/:/g, '-')
        const filename = `${
          type === 'video' ? '视频' : '音频'
        }_片段${segmentNumber}_${timestamp}.${format}`

        const a = document.createElement('a')
        a.href = URL.createObjectURL(blob)
        a.download = filename
        a.click()

        statusMessage.textContent = `📥 ${
          type === 'video' ? '视频' : '音频'
        }文件下载中...`
      }

      // 重置所有
      function resetAll() {
        if (confirm('🤔 确定要重置所有内容吗？')) {
          if (videoUrl) {
            URL.revokeObjectURL(videoUrl)
            videoUrl = null
          }

          inputFile = null
          videoBlob = null
          audioBlob = null
          currentVideo = null
          timeSegments = []

          videoInput.value = ''
          startTimeInput.value = ''
          endTimeInput.value = ''
          currentTimeDisplay.textContent = '00:00'

          originalPreview.innerHTML =
            '<p style="text-align: center; padding: 60px 20px; color: var(--text-secondary); font-size: 1.1rem;">📺 视频预览区</p>'
          updateSegmentsList()

          downloadSection.style.display = 'none'
          processBtn.disabled = true
          statusMessage.textContent = ''
          statusMessage.classList.remove('processing')
          errorMessage.textContent = ''
          progressFill.style.width = '0%'
          progressText.textContent = '🚀 准备就绪'
        }
      }

      // 显示错误信息
      function showError(message, element) {
        element.textContent = message
        element.classList.add('error-shake')
        setTimeout(() => {
          element.classList.remove('error-shake')
        }, 500)
      }

      // 格式化文件大小
      function formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes'
        const k = 1024
        const sizes = ['Bytes', 'KB', 'MB', 'GB']
        const i = Math.floor(Math.log(bytes) / Math.log(k))
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
      }

      // 检查文件格式是否支持预览
      function isPreviewSupported(type, format) {
        console.log(type, format)
        if (type === 'video') {
          // 浏览器支持的视频格式
          const supportedVideoFormats = ['mp4', 'webm', 'ogg']
          return supportedVideoFormats.includes(format.toLowerCase())
        } else if (type === 'audio') {
          // 浏览器支持的音频格式
          const supportedAudioFormats = ['mp3', 'wav', 'ogg', 'm4a', 'aac']
          return supportedAudioFormats.includes(format.toLowerCase())
        }
        return false
      }

      // 预览文件
      function previewFile(segmentData, type, videoFormat, audioFormat, segmentNumber) {
        const blob = type === 'video' ? segmentData.videoBlob : segmentData.audioBlob
        const format = type === 'video' ? videoFormat : audioFormat
        const url = URL.createObjectURL(blob)
        
        const previewModal = document.getElementById('previewModal')
        const previewTitle = document.getElementById('previewTitle')
        const previewContainer = document.getElementById('previewContainer')
        
        // 设置标题
        previewTitle.textContent = `${type === 'video' ? '视频' : '音频'}预览 - 片段${segmentNumber}`
        
        // 清空容器
        previewContainer.innerHTML = ''
        
        // 创建媒体元素
        let mediaElement
        if (type === 'video') {
          mediaElement = document.createElement('video')
          mediaElement.controls = true
          mediaElement.autoplay = false
        } else {
          mediaElement = document.createElement('audio')
          mediaElement.controls = true
          mediaElement.autoplay = false
        }
        
        mediaElement.src = url
        mediaElement.className = 'preview-media'
        
        // 添加错误处理
        mediaElement.onerror = function() {
          previewContainer.innerHTML = '<p style="text-align: center; color: var(--danger-color); padding: 40px;">❌ 预览失败，该格式可能不被浏览器支持</p>'
        }
        
        previewContainer.appendChild(mediaElement)
        
        // 显示弹窗
        previewModal.style.display = 'flex'
        
        // 清理URL（当弹窗关闭时）
        const cleanup = () => {
          URL.revokeObjectURL(url)
          if (mediaElement) {
            mediaElement.pause()
            mediaElement.src = ''
          }
        }
        
        // 存储清理函数以便关闭时调用
        previewModal._cleanup = cleanup
      }

      // 初始化预览弹窗事件
      function initPreviewModal() {
        const previewModal = document.getElementById('previewModal')
        const closeBtn = document.getElementById('closePreview')
        
        // 关闭按钮事件
        closeBtn.addEventListener('click', closePreviewModal)
        
        // 点击背景关闭
        previewModal.addEventListener('click', (e) => {
          if (e.target === previewModal) {
            closePreviewModal()
          }
        })
        
        // ESC键关闭
        document.addEventListener('keydown', (e) => {
          if (e.key === 'Escape' && previewModal.style.display === 'flex') {
            closePreviewModal()
          }
        })
      }

      // 关闭预览弹窗
      function closePreviewModal() {
        const previewModal = document.getElementById('previewModal')
        
        // 执行清理函数
        if (previewModal._cleanup) {
          previewModal._cleanup()
          previewModal._cleanup = null
        }
        
        previewModal.style.display = 'none'
      }

      // 初始化
      initEvents()
      initPreviewModal()
    </script>
  </body>
</html>
